using System;
using System.Collections;
using UnityEngine;

public class CharacterFighting : MonoBehaviour
{
	public AimHelper aimHelper;

	private Weapon weapon;

	private ConfigurableJoint holdWeaponJoint;

	public float rotationHoldForce = 500f;

	public float positionHoldForce = 100f;

	[SerializeField]
	private Rigidbody leftHand;

	[SerializeField]
	private Rigidbody rightHand;

	[SerializeField]
	private Rigidbody leftKnee;

	[SerializeField]
	private Rigidbody rightKnee;

	[SerializeField]
	private Rigidbody rightElbow;

	[SerializeField]
	private Rigidbody torso;

	[SerializeField]
	private Rigidbody rightArm;

	private CharacterPunch leftHandPunch;

	private CharacterPunch rightHandPunch;

	private CharacterPunch leftKneePunch;

	public Transform holdPosition;

	[SerializeField]
	private CharacterInformation info;

	public float sincePunch;

	private float punchCD;

	[HideInInspector]
	public float counter;

	public bool stopHit;

	public bool isSwinging;

	public float punchForce;

	public float punchTime;

	public AnimationCurve punchCurve;

	private bool hitLeft;

	public Action<bool> OnWeaponChange;

	public bool hasWeapon => weapon != null;

	private void Awake()
	{
		leftHandPunch = leftHand.gameObject.GetComponent<CharacterPunch>();
		rightHandPunch = rightHand.gameObject.GetComponent<CharacterPunch>();
		leftKneePunch = leftKnee.gameObject.GetComponent<CharacterPunch>();
	}

	private void Update()
	{
		if (hasWeapon)
		{
			HoldWeaponPosition(weapon.body, aimHelper.aimPosition.position + aimHelper.aimPosition.forward * 0.05f, positionHoldForce);
			HoldWeaponRotation(weapon.body, aimHelper.Value, rotationHoldForce);
		}
		counter += Time.deltaTime;
		sincePunch += Time.deltaTime;
		punchCD += Time.deltaTime;
	}

	private void HoldWeaponPosition(Rigidbody rig, Vector3 position, float force)
	{
		Vector3 a = position - rig.worldCenterOfMass;
		rig.AddForce(a * force * Time.deltaTime, ForceMode.Acceleration);
	}

	private void HoldWeaponRotation(Rigidbody rig, Vector3 aimDir, float force)
	{
		float d = Vector3.Angle(rig.transform.right, aimDir);
		Vector3 a = Vector3.Cross(rig.transform.right, aimDir);
		rig.AddTorque(a * d * force * 1f * Time.deltaTime, ForceMode.Acceleration);
	}

	public void PickupWeapon(Weapon weapon, bool forcePick)
	{
		if (hasWeapon)
		{
			if (!forcePick)
			{
				return;
			}
			DropWeapon();
		}
		weapon.transform.localScale = Vector3.one;
		weapon.body.angularDrag = 20f;
		info.PlayPickup();
		this.weapon = weapon;
		this.weapon.owner = info;
		weapon.transform.position = holdPosition.position;
		SetWeaponLayer(torso.gameObject.layer, weapon);
		holdWeaponJoint = AttachHand(rightHand, this.weapon.body);
		weapon.GetComponent<CharacterStayInDimension>().enabled = false;
		if (OnWeaponChange != null)
		{
			OnWeaponChange(obj: true);
		}
	}

	private ConfigurableJoint AttachHand(Rigidbody startRig, Rigidbody endRig)
	{
		ConfigurableJoint configurableJoint = startRig.gameObject.AddComponent<ConfigurableJoint>();
		configurableJoint.angularXMotion = ConfigurableJointMotion.Free;
		configurableJoint.angularYMotion = ConfigurableJointMotion.Free;
		configurableJoint.angularZMotion = ConfigurableJointMotion.Free;
		configurableJoint.xMotion = ConfigurableJointMotion.Locked;
		configurableJoint.yMotion = ConfigurableJointMotion.Locked;
		configurableJoint.zMotion = ConfigurableJointMotion.Locked;
		configurableJoint.projectionMode = JointProjectionMode.PositionAndRotation;
		configurableJoint.anchor = startRig.transform.InverseTransformPoint(endRig.transform.position);
		configurableJoint.connectedBody = endRig;
		return configurableJoint;
	}

	public void DropWeapon()
	{
		if (hasWeapon)
		{
			weapon.owner = null;
			weapon.body.AddForce(Vector3.up * 10f);
			weapon.body.AddTorque(Vector3.up * 1000f);
			weapon.GetComponent<CharacterStayInDimension>().enabled = true;
			StartCoroutine(FalseIgnorer(3f, weapon));
			if (holdWeaponJoint != null)
			{
				UnityEngine.Object.Destroy(holdWeaponJoint);
			}
			weapon.body.AddForce(Vector3.up * 50f, ForceMode.Impulse);
			weapon.body.AddTorque(Vector3.right * 1000000f, ForceMode.Acceleration);
			weapon.body.angularDrag = 0f;
			weapon.transform.localScale = Vector3.one * 1.25f;
			weapon = null;
			if (OnWeaponChange != null)
			{
				OnWeaponChange(obj: false);
			}
		}
	}

	private IEnumerator FalseIgnorer(float delay, Weapon w)
	{
		yield return new WaitForSeconds(delay);
		SetWeaponLayer(LayerMask.GetMask(LayerMask.LayerToName(0)), w);
	}

	private void SetWeaponLayer(LayerMask layer, Weapon w)
	{
		if (!(w == null))
		{
			Collider[] cols = w.cols;
			Collider[] array = cols;
			foreach (Collider collider in array)
			{
				collider.gameObject.layer = layer;
			}
		}
	}

	public void Attack()
	{
		bool flag = false;
		if (hasWeapon ? DoShoot() : DoPunch())
		{
			CameraShakeController.Instance.AddShake(-(aimHelper.aimTarget.position - aimHelper.aimPosition.position).normalized);
		}
	}

	private bool DoPunch()
	{
		if (sincePunch < 0.5f)
		{
			return false;
		}
		if (info.sinceGrounded > 0.3f || info.sinceJumped < 0.4f)
		{
			StartCoroutine(DoPunch(leftKnee, 3f, punchTime, punchCurve, leftKneePunch));
		}
		else
		{
			if (hitLeft)
			{
				StartCoroutine(DoPunch(leftHand, 1.5f, punchTime, punchCurve, leftHandPunch));
			}
			else
			{
				StartCoroutine(DoPunch(rightHand, 1.5f, punchTime, punchCurve, rightHandPunch));
			}
			hitLeft = !hitLeft;
		}
		return true;
	}

	private IEnumerator DoPunch(Rigidbody rig, float multiplier, float timeToPunch, AnimationCurve curve, CharacterPunch punchPart)
	{
		bool hasSetPunch = false;
		sincePunch = 0f;
		float t = 0f;
		punchPart.isSetPunch = true;
		info.GetComponent<CharacterParticles>().PlayPunchEffect(rig.transform.position, aimHelper.aimTarget.position);
		info.PlaySwing();
		while (t < 1f && info.isAlive && !stopHit)
		{
			yield return new WaitForFixedUpdate();
			if (curve.Evaluate(t) > 0f && !hasSetPunch)
			{
				hasSetPunch = true;
				isSwinging = true;
			}
			t += Time.fixedDeltaTime / timeToPunch;
			Vector3 dir = aimHelper.Value.normalized;
			rig.AddForce(dir * Time.fixedDeltaTime * multiplier * punchForce * curve.Evaluate(t), ForceMode.Acceleration);
			torso.AddForce(dir * Time.fixedDeltaTime * multiplier * punchForce * 0.03f * curve.Evaluate(t), ForceMode.Acceleration);
			rig.velocity *= 0.7f;
		}
		stopHit = false;
		isSwinging = false;
		punchPart.isSetPunch = false;
	}

	private bool DoShoot()
	{
		return weapon.Shoot(aimHelper.aimTarget.position);
	}
}
